﻿// License Notification
//======================================================
// Copyright (c) 2010 Channel Intelligence Inc.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// ======================================================


using System;
using System.Collections.Generic;
using CIP4.Common;
using CIP4.Item;

namespace CIP4.Simple
{
    public abstract class StrongWrapperBase
    {
        public static Dictionary<string, IWeakWrapper> Wrappers = new Dictionary<string, IWeakWrapper>();

        internal static string GetWrapperLabel<TSomeType>(CIP4ItemAttribute itemAttribute)
        {
            return string.Format("{0}:{1}", itemAttribute.Collection, typeof(TSomeType).Name);
        }

        internal static string GetWrapperLabel<TSomeType>(string targetCollection)
        {
            return string.Format("{0}:{1}", targetCollection, typeof(TSomeType).Name);
        }

        /// <summary>
        /// Use this factory method if you want the wrapper to be cached and usable by CIP4ReferenceType instances
        /// </summary>
        public static StrongWrapper<TSomeType> GetWrapper<TSomeType>(CIP4ItemAttribute itemAttribute, LoggerDelegate logger) where TSomeType : class
        {
            if (Wrappers.ContainsKey(GetWrapperLabel<TSomeType>(itemAttribute)))
                return (StrongWrapper<TSomeType>)Wrappers[GetWrapperLabel<TSomeType>(itemAttribute)];
            StrongWrapper<TSomeType> wrapper = new StrongWrapper<TSomeType>(itemAttribute, logger);
            Wrappers.Add(GetWrapperLabel<TSomeType>(itemAttribute), wrapper);
            return wrapper;
        }

        /// <summary>
        /// Use this factory method if you want the wrapper to be cached and usable by CIP4ReferenceType instances
        /// </summary>
        public static StrongWrapper<TSomeType> GetWrapper<TSomeType>(GetConnectionValuesDelegate getValues, LoggerDelegate logger) where TSomeType : class
        {
            CIP4ItemAttribute itemAttribute = CIP4ItemAttribute.GetAttribute(typeof(TSomeType));
            if (Wrappers.ContainsKey(GetWrapperLabel<TSomeType>(itemAttribute)))
                return (StrongWrapper<TSomeType>)Wrappers[GetWrapperLabel<TSomeType>(itemAttribute)];
            StrongWrapper<TSomeType> wrapper = new StrongWrapper<TSomeType>(getValues, logger);
            Wrappers.Add(GetWrapperLabel<TSomeType>(itemAttribute), wrapper);
            return wrapper;
        }

        /// <summary>
        /// Use this factory method if you want the wrapper to be cached and usable by CIP4ReferenceType instances
        /// </summary>
        public static StrongWrapper<TSomeType> GetWrapper<TSomeType>(CIP4ConnectionAttribute connection, LoggerDelegate logger) where TSomeType : class
        {
            CIP4ItemAttribute itemAttribute = CIP4ItemAttribute.GetAttribute(typeof(TSomeType));
            if (Wrappers.ContainsKey(GetWrapperLabel<TSomeType>(itemAttribute)))
                return (StrongWrapper<TSomeType>)Wrappers[GetWrapperLabel<TSomeType>(itemAttribute)];
            StrongWrapper<TSomeType> wrapper = new StrongWrapper<TSomeType>(connection, logger);
            Wrappers.Add(GetWrapperLabel<TSomeType>(itemAttribute), wrapper);
            return wrapper;
        }

        /// <summary>
        /// Use this factory method if you want the wrapper to be cached and usable by CIP4ReferenceType instances
        /// </summary>
        public static StrongWrapper<TSomeType> GetWrapper<TSomeType>(LoggerDelegate logger) where TSomeType : class
        {
            CIP4ItemAttribute itemAttribute = CIP4ItemAttribute.GetAttribute(typeof(TSomeType));
            if (Wrappers.ContainsKey(GetWrapperLabel<TSomeType>(itemAttribute)))
                return (StrongWrapper<TSomeType>)Wrappers[GetWrapperLabel<TSomeType>(itemAttribute)];
            StrongWrapper<TSomeType> wrapper = new StrongWrapper<TSomeType>(logger);
            Wrappers.Add(GetWrapperLabel<TSomeType>(itemAttribute), wrapper);
            return wrapper;
        }

        /// <summary>
        /// Especially for those adventurous souls that want to switch connections mid-stream - this will force
        /// all subsequent references to go to the newly established connection - could have some very odd results
        /// Use this factory method if you want the wrapper to be cached and usable by CIP4ReferenceType instances
        /// </summary>
        public static StrongWrapper<TSomeType> ReplaceWrapper<TSomeType>(CIP4ItemAttribute itemAttribute, LoggerDelegate logger) where TSomeType : class
        {
            if (Wrappers.ContainsKey(GetWrapperLabel<TSomeType>(itemAttribute)))
                Wrappers.Remove(GetWrapperLabel<TSomeType>(itemAttribute));
            return GetWrapper<TSomeType>(itemAttribute, logger);
        }

        /// <summary>
        /// Especially for those adventurous souls that want to switch connections mid-stream - this will force
        /// all subsequent references to go to the newly established connection - could have some very odd results
        /// Use this factory method if you want the wrapper to be cached and usable by CIP4ReferenceType instances
        /// </summary>
        public static StrongWrapper<TSomeType> ReplaceWrapper<TSomeType>(GetConnectionValuesDelegate getValues, LoggerDelegate logger) where TSomeType : class
        {
            CIP4ItemAttribute itemAttribute = CIP4ItemAttribute.GetAttribute(typeof(TSomeType));
            if (Wrappers.ContainsKey(GetWrapperLabel<TSomeType>(itemAttribute)))
                Wrappers.Remove(GetWrapperLabel<TSomeType>(itemAttribute));
            return GetWrapper<TSomeType>(getValues, logger);
        }

        /// <summary>
        /// Especially for those adventurous souls that want to switch connections mid-stream - this will force
        /// all subsequent references to go to the newly established connection - could have some very odd results
        /// Use this factory method if you want the wrapper to be cached and usable by CIP4ReferenceType instances
        /// </summary>
        public static StrongWrapper<TSomeType> ReplaceWrapper<TSomeType>(CIP4ConnectionAttribute connection, LoggerDelegate logger) where TSomeType : class
        {
            CIP4ItemAttribute itemAttribute = CIP4ItemAttribute.GetAttribute(typeof(TSomeType));
            if (Wrappers.ContainsKey(GetWrapperLabel<TSomeType>(itemAttribute)))
                Wrappers.Remove(GetWrapperLabel<TSomeType>(itemAttribute));
            return GetWrapper<TSomeType>(connection, logger);
        }

        /// <summary>
        /// Especially for those adventurous souls that want to switch connections mid-stream - this will force
        /// all subsequent references to go to the newly established connection - could have some very odd results
        /// Use this factory method if you want the wrapper to be cached and usable by CIP4ReferenceType instances
        /// </summary>
        public static StrongWrapper<TSomeType> ReplaceWrapper<TSomeType>(LoggerDelegate logger) where TSomeType : class
        {
            CIP4ItemAttribute itemAttribute = CIP4ItemAttribute.GetAttribute(typeof(TSomeType));
            if (Wrappers.ContainsKey(GetWrapperLabel<TSomeType>(itemAttribute)))
                Wrappers.Remove(GetWrapperLabel<TSomeType>(itemAttribute));
            return GetWrapper<TSomeType>(logger);
        }

        public int PageSize { get; set; }

        public abstract IEnumerable<ExternalIDType> ExternalIdsForItems(IEnumerable<object> items);

        public abstract ISerializerType GetSerializer(SerializerKindEnum serializerKind);

        public abstract Type GetWrapperType();

        public abstract CIP4ItemAttribute ItemAttribute { get; protected set; }

        public abstract CIP4ConnectionAttribute ClassConnectionAttribute { get; }

        public abstract LoggerDelegate Logger { get; set; }

    }

}